home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / win_u_z / vlistsam.zip / VLIST.C < prev    next >
C/C++ Source or Header  |  1992-09-27  |  34KB  |  1,141 lines

  1. #include "vlistint.h"
  2. #include "string.h"
  3.  
  4. #define _LB_MOUSESCROLL         0x0118
  5.  
  6.  
  7. LRESULT _export CALLBACK VListBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  8. {
  9.   PVLBOX pVLBox;
  10.   LONG lRetVal;
  11.  
  12.   /* Get the pVLBox for the given window now since we will use it a lot in
  13.    * various handlers. This was stored using SetWindowWord(hwnd,0,pVLBox) when
  14.    * we initially created the Virtual List Box control.
  15.    */
  16.  
  17.    pVLBox = (PVLBOX) GetWindowWord(hwnd,0);
  18.  
  19.    if (message != WM_NCCREATE && (WORD)pVLBox == (WORD)-1)
  20.        // The pVLBox was destroyed and this is a rogue message to be ignored.
  21.        return(0L);
  22.  
  23.   /* Dispatch the various messages we can receive */
  24.   switch (message)
  25.   {
  26.     case VLB_INITIALIZE:
  27.       SetScrollRange(pVLBox->hwndList, SB_VERT, 0, 100, TRUE);
  28.       SendMessage(pVLBox->hwndParent, VLB_RANGE, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  29.       if ( pVLBox->vlbStruct.nStatus == VLB_OK ) {
  30.          pVLBox->lNumLogicalRecs = pVLBox->vlbStruct.lIndex;
  31.       }
  32.       else {
  33.          pVLBox->lNumLogicalRecs = -1L;
  34.          pVLBox->wFlags = pVLBox->wFlags | USEDATAVALUES;
  35.       }
  36.  
  37.       if ( pVLBox->styleSave & VLBS_USEDATAVALUES )
  38.          pVLBox->wFlags & USEDATAVALUES;
  39.  
  40.       VLBFirstPage(pVLBox);
  41.       return VLB_OK;
  42.  
  43.       break;
  44.  
  45.     case WM_VSCROLL:
  46.        switch(wParam) {
  47.           case SB_LINEDOWN:
  48.               VLBScrollDownLine(pVLBox);
  49.               SetSelectedItem(pVLBox);
  50.           break;
  51.  
  52.           case SB_PAGEDOWN:
  53.               VLBScrollDownPage(pVLBox, 0);
  54.               SetSelectedItem(pVLBox);
  55.           break;
  56.  
  57.           case SB_LINEUP:
  58.               VLBScrollUpLine(pVLBox);
  59.               SetSelectedItem(pVLBox);
  60.           break;
  61.  
  62.           case SB_PAGEUP:
  63.               VLBScrollUpPage(pVLBox, 0);
  64.               SetSelectedItem(pVLBox);
  65.           break;
  66.  
  67.           case SB_TOP:
  68.               VLBFirstPage(pVLBox);
  69.               SetSelectedItem(pVLBox);
  70.           break;
  71.  
  72.           case SB_BOTTOM:
  73.               VLBLastPage(pVLBox);
  74.               SetSelectedItem(pVLBox);
  75.           break;
  76.  
  77.           case SB_THUMBPOSITION:
  78.             {
  79.               int nPos;
  80.               nPos = LOWORD(lParam);
  81.               if ( nPos == 0 ) {
  82.                  VLBFirstPage(pVLBox);
  83.                  break;
  84.               }
  85.               else if ( nPos == 100 ) {
  86.                  VLBLastPage(pVLBox);
  87.                  break;
  88.               }
  89.  
  90.               if ( pVLBox->wFlags & USEDATAVALUES ) {
  91.                     if ( VLBFindPos(pVLBox, nPos) )
  92.                         return VLB_ERR;
  93.                     else
  94.                         SetSelectedItem(pVLBox);
  95.               }
  96.               else {
  97.                  if ( VLBFindPage(pVLBox,
  98.                  (((LONG)LOWORD(lParam)
  99.                    *(pVLBox->lNumLogicalRecs-pVLBox->nLines+1))/100L), TRUE) )
  100.                     return VLB_ERR;
  101.                  else
  102.                     SetSelectedItem(pVLBox);
  103.               }
  104.             }
  105.           break;
  106.  
  107.        }
  108.        return((LONG)TRUE);
  109.        break;
  110.  
  111.     case WM_COMMAND:
  112.       /* So that we can handle notification messages from the listbox.
  113.        */
  114.       if ( HIWORD(lParam) == LBN_SELCHANGE ) {
  115.          SetSelectedItem(pVLBox);
  116.       }
  117.       else if (HIWORD(lParam) == LBN_SELCANCEL) {
  118.          pVLBox->lSelItem = -1L;
  119.       }
  120.       if (pVLBox->styleSave & VLBS_NOTIFY ) {
  121.          return(VLBParentMessageHandler(pVLBox, message, (WPARAM)(WORD)pVLBox->nId, lParam));
  122.       }
  123.       else {
  124.          return TRUE;
  125.       }
  126.       break;
  127.  
  128.     case WM_CHARTOITEM: {
  129.            long lRet;
  130.  
  131.            if (pVLBox->styleSave & VLBS_WANTKEYBOARDINPUT ) {
  132.               lRet = VLBParentMessageHandler(pVLBox, WM_CHARTOITEM, wParam, lParam);
  133.            }
  134.            else {
  135.               lRet = -1;
  136.            }
  137.  
  138.            return lRet;
  139.         }
  140.         break;
  141.  
  142.     case WM_VKEYTOITEM: {
  143.            int iCaret = HIWORD(lParam);
  144.            long lRet;
  145.  
  146.            if (pVLBox->styleSave & VLBS_WANTKEYBOARDINPUT ) {
  147.               lRet = VLBParentMessageHandler(pVLBox, WM_VKEYTOITEM, wParam, lParam);
  148.            }
  149.            else {
  150.               lRet = -1;
  151.            }
  152.  
  153.            if ( lRet == -1 ) {
  154.               switch(wParam) {
  155.                  case VK_DOWN:
  156.                     vlbLineDn(pVLBox);
  157.                     return -2;
  158.                  break;
  159.  
  160.                  case VK_UP:
  161.                     vlbLineUp(pVLBox);
  162.                     return -2;
  163.                  break;
  164.  
  165.                  case VK_PRIOR:
  166.                      vlbPGUP(pVLBox);
  167.                      return -2;
  168.                  break;
  169.  
  170.                  case VK_NEXT:
  171.                      vlbPGDN(pVLBox);
  172.                      return -2;
  173.                  break;
  174.  
  175.                  case VK_HOME:
  176.                      VLBFirstPage(pVLBox);
  177.                      SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  178.                      SetSelectedItem(pVLBox);
  179.                      return -2;
  180.                  break;
  181.  
  182.                  case VK_END:
  183.                   {
  184.                      int nLastLine;
  185.  
  186.                      if ( (pVLBox->nLines-1) < pVLBox->nCountInBox )
  187.                         nLastLine = pVLBox->nLines-1;
  188.                      else
  189.                         nLastLine = pVLBox->nCountInBox-1;
  190.  
  191.                      VLBLastPage(pVLBox);
  192.                      SendMessage(pVLBox->hwndList, LB_SETCURSEL, nLastLine, 0L);
  193.                      SetSelectedItem(pVLBox);
  194.                      return -2;
  195.                   }
  196.                  break;
  197.               }
  198.            }
  199.            return lRet;
  200.         }
  201.         break;
  202.  
  203.     case _LB_MOUSESCROLL:
  204.        {
  205.          //
  206.          // The user is holding the mouse down outside the LB....
  207.          // Scroll the VLB as needed.
  208.          //
  209.          // Dont need to LB_SETCURSEL since the LB is going to do this for us.
  210.          //
  211.          int nSelected;
  212.  
  213.          nSelected = (int)SendMessage(pVLBox->hwndList, LB_GETCURSEL, 0, 0L);
  214.          if ( nSelected == pVLBox->nLines-1 ) {
  215.             VLBScrollDownLine(pVLBox);
  216.             SetSelectedItem(pVLBox);
  217.          }
  218.          else if ( nSelected == 0 ) {
  219.             VLBScrollUpLine(pVLBox);
  220.             SetSelectedItem(pVLBox);
  221.          }
  222.          //
  223.          // Values doesn't mean much since this messsage is passed back to
  224.          // original LB proc
  225.          //
  226.          return 0L;
  227.       }
  228.       break;
  229.  
  230.     case WM_CREATE:
  231.       /* wParam - not used
  232.          lParam - Points to the CREATESTRUCT data structure for the window.
  233.        */
  234.       return(VLBCreateHandler(pVLBox, hwnd, (LPCREATESTRUCT)lParam));
  235.       break;
  236.  
  237.     case WM_ERASEBKGND:
  238.       /* Just return 1L so that the background isn't erased */
  239.       return((LONG)TRUE);
  240.       break;
  241.  
  242.     case WM_GETFONT:
  243.        return((LONG)(LONG)(WORD)(pVLBox->hFont));
  244.        break;
  245.  
  246.     case WM_GETDLGCODE:
  247.       /* wParam - not used
  248.          lParam - not used */
  249.       return((LONG)(LONG)(DLGC_WANTCHARS | DLGC_WANTARROWS));
  250.       break;
  251.  
  252.     case WM_SETFONT:
  253.       VLBSetFontHandler(pVLBox, (HANDLE)wParam, LOWORD(lParam));
  254.       break;
  255.  
  256.     case WM_LBUTTONDOWN:
  257.     case WM_MBUTTONDOWN:
  258.     case WM_RBUTTONDOWN:
  259.     case WM_KEYDOWN:
  260.        // Set the focus to the Virtual List Box if we get a mouse click
  261.        // or key press on the parent window.
  262.        SetFocus(pVLBox->hwndList);
  263.        SendMessage(pVLBox->hwndList, message, wParam, lParam);
  264.       break;
  265.  
  266.     case WM_NCDESTROY:
  267.       /* wParam - used by DefWndProc called within VLBNcDestroyHandler
  268.          lParam - used by DefWndProc called within VLBNcDestroyHandler */
  269.       VLBNcDestroyHandler(hwnd, pVLBox, wParam, lParam);
  270.       break;
  271.  
  272.     case WM_KILLFOCUS:
  273.           if ( (HWND) wParam != pVLBox->hwndList )
  274.               pVLBox->wFlags  &= ~HASFOCUS;
  275.  
  276.       break;
  277.  
  278.     case WM_SETFOCUS:
  279.         {
  280.           int i;
  281.  
  282.           pVLBox->wFlags  |= HASFOCUS;
  283.  
  284.           if ( ! (pVLBox->wFlags & PARENTFOCUS) ) {
  285.              if ( (i=vlbInVLB(pVLBox, pVLBox->lSelItem)) >= 0 ) {
  286.                 pVLBox->wFlags &= ~PARENTFOCUS;
  287.                 SetFocus(pVLBox->hwndList);
  288.              }
  289.              else {
  290.                 pVLBox->wFlags |= PARENTFOCUS;
  291.              }
  292.           }
  293.         }
  294.       break;
  295.  
  296.     case WM_SETREDRAW:
  297.       /* wParam - specifies state of the redraw flag. nonzero = redraw
  298.          lParam - not used */
  299.       if ( wParam) {
  300.          vlbRedrawOn(pVLBox);
  301.       }
  302.       else {
  303.          vlbRedrawOff(pVLBox);
  304.       }
  305.       return TRUE;
  306.       break;
  307.  
  308.     case WM_ENABLE:
  309.       /* Invalidate the rect to cause it to be drawn in grey for its disabled
  310.        * view or ungreyed for non-disabled view.
  311.        */
  312.       InvalidateRect(pVLBox->hwnd, NULL, FALSE);
  313.       /* Enable/disable the listbox window
  314.        */
  315.       EnableWindow(pVLBox->hwndList, wParam);
  316.       // EnableWindow(pVLBox->hwndScroll, wParam);
  317.       break;
  318.  
  319.     case WM_SIZE:
  320.       /* wParam - defines the type of resizing fullscreen, sizeiconic,
  321.                   sizenormal etc.
  322.          lParam - new width in LOWORD, new height in HIGHWORD of client area */
  323.       if (!LOWORD(lParam) || !HIWORD(lParam) || !pVLBox->hwndList)
  324.           /* If being sized to a zero width or to a zero height or we aren't
  325.         * fully initialized, just return.
  326.         */
  327.           return(0);
  328.       VLBSizeHandler(pVLBox, 0);
  329.       break;
  330.  
  331.     case VLB_FINDSTRING:
  332.     case VLB_FINDSTRINGEXACT:
  333.     case VLB_SELECTSTRING:
  334.        {
  335.           VLBSTRUCT FAR *lpvlbInStruct;
  336.  
  337.           lpvlbInStruct = (LPVLBSTRUCT)lParam;
  338.  
  339.           pVLBox->vlbStruct.lIndex       = lpvlbInStruct->lIndex;
  340.           pVLBox->vlbStruct.lData         = lpvlbInStruct->lData;
  341.           pVLBox->vlbStruct.lpFindString  = lpvlbInStruct->lpFindString;
  342.           pVLBox->vlbStruct.lpTextPointer = NULL;
  343.  
  344.           SendMessage(pVLBox->hwndParent, message, 0,  (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  345.           if ( pVLBox->vlbStruct.nStatus == VLB_OK ) {
  346.              if ( pVLBox->wFlags & USEDATAVALUES )
  347.                 lRetVal = pVLBox->vlbStruct.lData;
  348.              else
  349.                 lRetVal = pVLBox->vlbStruct.lIndex;
  350.  
  351.              if ( message != VLB_SELECTSTRING ) {
  352.                 return lRetVal;
  353.              }
  354.  
  355.              if ( pVLBox->wFlags & USEDATAVALUES ) {
  356.                 //
  357.                 // Strings or search for data
  358.                 //
  359.                 int i;
  360.                 if ( (i=vlbFindData(pVLBox, pVLBox->vlbStruct.lData)) != LB_ERR ) {
  361.                     SendMessage(pVLBox->hwndList, LB_SETCURSEL, i, 0L);
  362.                     SetSelectedItem(pVLBox);
  363.                     return lRetVal;
  364.                 }
  365.                 else {
  366.                    if ( VLBFindPage(pVLBox, pVLBox->vlbStruct.lData, TRUE) )
  367.                         return VLB_ERR;
  368.  
  369.                    SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  370.                    SetSelectedItem(pVLBox);
  371.                    return lRetVal;
  372.                 }
  373.              }
  374.              else {
  375.                 //
  376.                 // Is this item in the list box now ??
  377.                 //
  378.                 if ( pVLBox->vlbStruct.lIndex >= pVLBox->lToplIndex &&
  379.                      pVLBox->vlbStruct.lIndex <= (pVLBox->lToplIndex+(LONG)(pVLBox->nCountInBox)-1)) {
  380.                      int nItemNum;
  381.  
  382.                      nItemNum = (int) (pVLBox->vlbStruct.lIndex-pVLBox->lToplIndex);
  383.                      SendMessage(pVLBox->hwndList, LB_SETCURSEL, nItemNum, 0L);
  384.                      SetSelectedItem(pVLBox);
  385.                      return lRetVal;
  386.                 }
  387.                 //
  388.                 // OK Adjust to show item
  389.                 //
  390.                 if ( VLBFindPage(pVLBox, pVLBox->vlbStruct.lIndex, TRUE) )
  391.                     return VLB_ERR;
  392.  
  393.                 SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  394.                 SetSelectedItem(pVLBox);
  395.                 return lRetVal;
  396.              }
  397.           }
  398.           else
  399.              return VLB_ERR;
  400.        }
  401.       break;
  402.  
  403.     case VLB_RESETCONTENT:
  404.       SendMessage(pVLBox->hwndList, LB_RESETCONTENT, 0, 0L);
  405.       SendMessage(pVLBox->hwndParent, VLB_RANGE, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  406.       if ( pVLBox->vlbStruct.nStatus == VLB_OK )
  407.          pVLBox->lNumLogicalRecs = pVLBox->vlbStruct.lIndex;
  408.       else {
  409.          pVLBox->lNumLogicalRecs = -1L;
  410.          pVLBox->wFlags & USEDATAVALUES;
  411.       }
  412.  
  413.       VLBFirstPage(pVLBox);
  414.       return VLB_OK;
  415.       break;
  416.  
  417.     case VLB_SETCURSEL:
  418.        // wParam Has Set Option:
  419.        //   VLBC_FIRST
  420.        //   VLBC_PREV
  421.        //   VLBC_NEXT
  422.        //   VLBC_LAST
  423.        //   VLBC_FINDITEM
  424.        //
  425.        //  lParam has the item number or item data
  426.        return ( vlbSetCurSel(pVLBox, wParam, lParam) );
  427.        break;
  428.  
  429.     case VLB_UPDATEPAGE:
  430.          SendMessage(pVLBox->hwndParent, VLB_RANGE, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  431.          if ( pVLBox->vlbStruct.nStatus == VLB_OK ) {
  432.             pVLBox->lNumLogicalRecs = pVLBox->vlbStruct.lIndex;
  433.          }
  434.          else {
  435.             pVLBox->lNumLogicalRecs = -1L;
  436.             pVLBox->wFlags & USEDATAVALUES;
  437.          }
  438.  
  439.          if ( pVLBox->lNumLogicalRecs <= pVLBox->nLines ) {
  440.             VLBFirstPage(pVLBox);
  441.          }
  442.          else if ( pVLBox->wFlags & USEDATAVALUES ) {
  443.              if ( VLBFindPage(pVLBox, SendMessage(pVLBox->hwndList, LB_GETITEMDATA, 0, 0L), FALSE ) )
  444.                 return VLB_ERR;
  445.          }
  446.          else {
  447.              if ( VLBFindPage(pVLBox, pVLBox->lToplIndex, FALSE) )
  448.                 return VLB_ERR;
  449.          }
  450.        break;
  451.  
  452.     case VLB_PAGEUP:
  453.          VLBScrollUpPage(pVLBox, wParam);
  454.          break;
  455.  
  456.     case VLB_PAGEDOWN:
  457.          VLBScrollDownPage(pVLBox, wParam);
  458.          break;
  459.  
  460.     case VLB_GETCURSEL:
  461.          return pVLBox->lSelItem;
  462.          break;
  463.  
  464.     case VLB_GETLINES:
  465.          return (LONG)pVLBox->nLines;
  466.          break;
  467.  
  468.     case LB_ADDSTRING:
  469.     case LB_INSERTSTRING:
  470.     case LB_DELETESTRING:
  471.     case LB_RESETCONTENT:
  472.     case LB_SETSEL:
  473.     case LB_SETCURSEL:
  474.     case LB_GETSEL:
  475.     case LB_GETCURSEL:
  476.     case LB_GETTEXT:
  477.     case LB_GETTEXTLEN:
  478.     case LB_GETCOUNT:
  479.     case LB_SELECTSTRING:
  480.     case LB_DIR:
  481.     case LB_GETTOPINDEX:
  482.     case LB_FINDSTRING:
  483.     case LB_GETSELCOUNT:
  484.     case LB_GETSELITEMS:
  485.     case LB_SETTABSTOPS:
  486.     case LB_GETHORIZONTALEXTENT:
  487.     case LB_SETHORIZONTALEXTENT:
  488.     case LB_SETCOLUMNWIDTH:
  489.     case LB_SETTOPINDEX:
  490.     case LB_GETITEMRECT:
  491.     case LB_GETITEMDATA:
  492.     case LB_SETITEMDATA:
  493.     case LB_SELITEMRANGE:
  494.     case LB_SETCARETINDEX:
  495.     case LB_GETCARETINDEX:
  496.     case LB_SETITEMHEIGHT:
  497.     case LB_GETITEMHEIGHT:
  498.     case LB_FINDSTRINGEXACT:
  499.          return(SendMessage(pVLBox->hwndList, message, wParam, lParam));
  500.          break;
  501.  
  502.     case VLB_GETITEMDATA:
  503.         {
  504.           LPVLBSTRUCT lpvlbInStruct;
  505.           int i;
  506.           LPARAM SendlParam;
  507.  
  508.  
  509.           lpvlbInStruct = (LPVLBSTRUCT)lParam;
  510.  
  511.           if (pVLBox->wFlags & USEDATAVALUES) {
  512.              SendlParam = lpvlbInStruct->lIndex;
  513.           }
  514.           else {
  515.              SendlParam = lpvlbInStruct->lData;
  516.           }
  517.  
  518.           if ( (i=vlbInVLB(pVLBox, SendlParam)) >= 0 ) {
  519.              return(SendMessage(pVLBox->hwndList, LB_GETITEMDATA, i, 0L));
  520.           }
  521.           else {
  522.              pVLBox->vlbStruct.lData = pVLBox->vlbStruct.lIndex = lParam;
  523.              SendMessage(pVLBox->hwndParent, VLB_GETITEMDATA, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  524.              if ( pVLBox->vlbStruct.nStatus == VLB_OK )
  525.                 return pVLBox->vlbStruct.lData;
  526.              else
  527.                 return VLB_ERR;
  528.           }
  529.         }
  530.         break;
  531.  
  532.     case VLB_GETCOUNT:
  533.       return pVLBox->lNumLogicalRecs;
  534.  
  535.     case VLB_GETTEXT:
  536.         {
  537.           LPVLBSTRUCT lpvlbInStruct;
  538.           int i;
  539.           LPARAM SendlParam;
  540.  
  541.           lpvlbInStruct = (LPVLBSTRUCT)lParam;
  542.  
  543.           if (pVLBox->wFlags & USEDATAVALUES) {
  544.              SendlParam = lpvlbInStruct->lIndex;
  545.           }
  546.           else {
  547.              SendlParam = lpvlbInStruct->lData;
  548.           }
  549.  
  550.           if ( (i=vlbInVLB(pVLBox, SendlParam)) >= 0 ) {
  551.              return(SendMessage(pVLBox->hwndList, LB_GETTEXT, i, (LPARAM)lpvlbInStruct->lpTextPointer));
  552.           }
  553.           else {
  554.              pVLBox->vlbStruct.lData = pVLBox->vlbStruct.lIndex = lParam;
  555.              SendMessage(pVLBox->hwndParent, VLB_GETTEXT, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  556.              if ( pVLBox->vlbStruct.nStatus == VLB_OK ) {
  557.                 _fstrcpy(lpvlbInStruct->lpTextPointer, pVLBox->vlbStruct.lpTextPointer);
  558.                 return _fstrlen(pVLBox->vlbStruct.lpTextPointer);
  559.              }
  560.              else
  561.                 return VLB_ERR;
  562.           }
  563.         }
  564.         break;
  565.  
  566.     case VLB_GETTEXTLEN:
  567.         {
  568.           int i;
  569.  
  570.  
  571.           if ( (i=vlbInVLB(pVLBox, lParam)) >= 0 ) {
  572.              return(SendMessage(pVLBox->hwndList, LB_GETTEXTLEN, i, 0L));
  573.           }
  574.           else {
  575.              pVLBox->vlbStruct.lData = pVLBox->vlbStruct.lIndex = lParam;
  576.              return SendMessage(pVLBox->hwndParent, VLB_GETTEXTLEN, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  577.           }
  578.         }
  579.         break;
  580.  
  581.     case VLB_SETITEMDATA:
  582.         {
  583.           LPVLBSTRUCT lpvlbInStruct;
  584.           int i;
  585.           LPARAM SendlParam;
  586.  
  587.           lpvlbInStruct = (LPVLBSTRUCT)lParam;
  588.  
  589.           if (pVLBox->wFlags & USEDATAVALUES) {
  590.              SendlParam = lpvlbInStruct->lIndex;
  591.           }
  592.           else {
  593.              SendlParam = lpvlbInStruct->lData;
  594.           }
  595.  
  596.           if ( (i=vlbInVLB(pVLBox, SendlParam)) >= 0 ) {
  597.              return(SendMessage(pVLBox->hwndList, LB_SETITEMDATA, i, (LPARAM)lpvlbInStruct->lIndex));
  598.           }
  599.           else return VLB_ERR;
  600.         }
  601.         break;
  602.  
  603.     case VLB_SETITEMHEIGHT:
  604.           return SendMessage(pVLBox->hwndList, LB_SETITEMHEIGHT, 0, lParam);
  605.         break;
  606.  
  607.     case VLB_GETITEMHEIGHT:
  608.           return SendMessage(pVLBox->hwndList, LB_GETITEMHEIGHT, 0, 0L);
  609.         break;
  610.  
  611.     case VLB_GETITEMRECT:
  612.         {
  613.           LPVLBSTRUCT lpvlbInStruct;
  614.           int i;
  615.  
  616.           lpvlbInStruct = (LPVLBSTRUCT)lParam;
  617.  
  618.           if ( (i=vlbInVLB(pVLBox, lParam)) >= 0 ) {
  619.              return(SendMessage(pVLBox->hwndList, LB_GETITEMRECT, i, (LPARAM)lpvlbInStruct->lIndex));
  620.           }
  621.           else return VLB_ERR;
  622.         }
  623.         break;
  624.  
  625.     case VLB_GETHORIZONTALEXTENT:
  626.           return SendMessage(pVLBox->hwndList, LB_GETHORIZONTALEXTENT, 0, 0L);
  627.         break;
  628.  
  629.     case VLB_SETHORIZONTALEXTENT:
  630.           return SendMessage(pVLBox->hwndList, LB_SETHORIZONTALEXTENT, wParam, 0L);
  631.         break;
  632.  
  633.     case VLB_SETTOPINDEX:
  634.         {
  635.           int i, nScroll;
  636.  
  637.           if ( (i=vlbInVLB(pVLBox, lParam)) > 0 ) {
  638.              nScroll = (int)(-1*(pVLBox->nLines-i));
  639.              VLBScrollDownPage(pVLBox, nScroll);
  640.           }
  641.           else if ( pVLBox->wFlags & USEDATAVALUES ) {
  642.              if ( VLBFindPage(pVLBox, lParam, TRUE ));
  643.                 return VLB_ERR;
  644.           }
  645.           else {
  646.              if ( VLBFindPage(pVLBox, lParam, TRUE) )
  647.                 return VLB_ERR;
  648.           }
  649.  
  650.         }
  651.         break;
  652.  
  653.     case VLB_GETTOPINDEX:
  654.           return SendMessage(pVLBox->hwndList, LB_GETTOPINDEX, 0, 0L);
  655.         break;
  656.  
  657.     case WM_MEASUREITEM:
  658.     case WM_DELETEITEM:
  659.     case WM_DRAWITEM:
  660.     case WM_COMPAREITEM:
  661.       return(VLBMessageItemHandler(pVLBox, message, (LPSTR)lParam));
  662.       break;
  663.  
  664.     case WM_NCCREATE:
  665.       /* wParam - Contains a handle to the window being created
  666.          lParam - Points to the CREATESTRUCT data structure for the window.
  667.        */
  668.       return(VLBNcCreateHandler(hwnd, (LPCREATESTRUCT)lParam));
  669.       break;
  670.  
  671.     default:
  672.       return(DefWindowProc(hwnd,message,wParam,lParam));
  673.  
  674.   } /* switch (message) */
  675.  
  676.   return((LONG)(LONG)TRUE);
  677. } /* VListBoxWndProc */
  678.  
  679.  
  680. LONG VLBMessageItemHandler( PVLBOX pVLBox,  WORD message, LPSTR lpfoo)
  681. /*
  682.  * effects: Handles WM_DRAWITEM,WM_MEASUREITEM,WM_DELETEITEM,WM_COMPAREITEM
  683.  * messages from the listbox.
  684.  */
  685. {
  686.   /*
  687.    * Send the <foo>item message back to the application after changing some
  688.    * parameters to their Virtual List Box specific versions.
  689.    */
  690.   long lRetVal;
  691.  
  692.   ((LPMEASUREITEMSTRUCT)lpfoo)->CtlType = ODT_LISTBOX;
  693.   ((LPMEASUREITEMSTRUCT)lpfoo)->CtlID   = (WORD)pVLBox->nId;
  694.  
  695.   if (message == WM_DRAWITEM)
  696.       ((LPDRAWITEMSTRUCT)lpfoo)->hwndItem    = pVLBox->hwnd;
  697.   else if (message == WM_DELETEITEM)
  698.       ((LPDELETEITEMSTRUCT)lpfoo)->hwndItem  = pVLBox->hwnd;
  699.   else if (message == WM_COMPAREITEM)
  700.       ((LPCOMPAREITEMSTRUCT)lpfoo)->hwndItem  = pVLBox->hwnd;
  701.  
  702.   lRetVal = SendMessage(pVLBox->hwndParent, message,
  703.                     (WPARAM)(WORD)pVLBox->nId, (LPARAM)lpfoo);
  704.  
  705.   if (message == WM_MEASUREITEM ) {
  706.      // Size the list box based on height in message
  707.      VLBSizeHandler( pVLBox , ((LPMEASUREITEMSTRUCT)lpfoo)->itemHeight);
  708.   }
  709.  
  710.   return lRetVal;
  711.  
  712. }
  713.  
  714.  
  715. LONG VLBParentMessageHandler( PVLBOX pVLBox, UINT message, WPARAM wParam, LPARAM lParam)
  716. {
  717.   return SendMessage(pVLBox->hwndParent,
  718.               message,
  719.               wParam,
  720.               MAKELPARAM(pVLBox->hwnd, HIWORD(lParam) ) );
  721.  
  722. }
  723.  
  724.  
  725.  
  726. int vlbInVLB( PVLBOX pVLBox, LONG lData)
  727. {
  728.    int i;
  729.  
  730.    if ( pVLBox->wFlags & USEDATAVALUES ) {
  731.       if ( (i=vlbFindData(pVLBox, lData)) != LB_ERR ) {
  732.         return i;
  733.       }
  734.       else {
  735.         return  VLB_ERR;
  736.       }
  737.    }
  738.    else {
  739.       if ( lData >= pVLBox->lToplIndex &&
  740.            lData <= (pVLBox->lToplIndex+(LONG)(pVLBox->nCountInBox)-1)) {
  741.         return (int) (lData - pVLBox->lToplIndex);
  742.       }
  743.       else {
  744.         return  VLB_ERR;
  745.       }
  746.    }
  747. }
  748.  
  749. int vlbFindData( PVLBOX pVLBox, LONG lData)
  750. {
  751.    int i;
  752.  
  753.    i = 0;
  754.    while ( i < pVLBox->nCountInBox ) {
  755.       if ( SendMessage(pVLBox->hwndList, LB_GETITEMDATA, i, 0L) == lData )
  756.          return i;
  757.       i++;
  758.    }
  759.  
  760.    return VLB_ERR;
  761.  
  762. }
  763.  
  764. void vlbRedrawOff(PVLBOX pVLBox)
  765. {
  766.      pVLBox->nvlbRedrawState--;
  767.      if ( pVLBox->nvlbRedrawState == 0 ) {
  768.         SendMessage(pVLBox->hwndList, WM_SETREDRAW, 0, 0L);
  769.      }
  770. }
  771.  
  772. void vlbRedrawOn(PVLBOX pVLBox)
  773. {
  774.      pVLBox->nvlbRedrawState++;
  775.      if ( pVLBox->nvlbRedrawState == 1 ) {
  776.         SendMessage(pVLBox->hwndList, WM_SETREDRAW, 1, 0L);
  777.         InvalidateRect(pVLBox->hwnd, NULL, FALSE);
  778.      }
  779. }
  780.  
  781.  
  782. //
  783. // List Box subclass function
  784. //
  785.  
  786. LRESULT  CALLBACK _loadds LBSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  787. {
  788.     PVLBOX pVLBox;
  789.  
  790.     switch (message) {
  791.     case WM_VSCROLL:
  792.         //
  793.         // Handle all the scrolling in the Vlist proc
  794.         //
  795.         return SendMessage(GetParent(hwnd), message, wParam, lParam);
  796.  
  797.     case _LB_MOUSESCROLL:
  798.         //
  799.         // Check for scroll then pass message on the the LB
  800.         //
  801.         SendMessage(GetParent(hwnd), message, wParam, lParam);
  802.       break;
  803.  
  804.     default:
  805.         break;
  806.     }
  807.  
  808.     //
  809.     // call the old window proc
  810.     //
  811.     pVLBox = (PVLBOX) GetWindowWord(GetParent(hwnd),0);
  812.  
  813.     if ( message == WM_SETFOCUS ) {
  814.           pVLBox->wFlags  |= HASFOCUS;
  815.     }
  816.  
  817.     return CallWindowProc((WNDPROC)pVLBox->lpfnLBWndProc , hwnd, message,
  818.                           (WPARAM) wParam, (LPARAM)lParam);
  819.  
  820. }
  821.  
  822.  
  823. BOOL TestSelectedItem(PVLBOX pVLBox, VLBSTRUCT vlbStruct)
  824. {
  825.     if ( pVLBox->wFlags & USEDATAVALUES ) {
  826.        if ( pVLBox->lSelItem == vlbStruct.lData )
  827.          return TRUE;
  828.        else
  829.          return FALSE;
  830.     }
  831.     else {
  832.        if ( pVLBox->lSelItem == vlbStruct.lIndex )
  833.          return TRUE;
  834.        else
  835.          return FALSE;
  836.     }
  837. }
  838.  
  839. void SetSelectedItem(PVLBOX pVLBox)
  840. {
  841.     int nSelected;
  842.  
  843.     nSelected = (int)SendMessage(pVLBox->hwndList, LB_GETCURSEL, 0, 0L);
  844.     if ( pVLBox->wFlags & USEDATAVALUES ) {
  845.        pVLBox->lSelItem =
  846.             SendMessage(pVLBox->hwndList, LB_GETITEMDATA, nSelected, 0L);
  847.     }
  848.     else {
  849.        pVLBox->lSelItem = (LONG)nSelected + pVLBox->lToplIndex;
  850.     }
  851. }
  852.  
  853. void vlbLineDn(PVLBOX pVLBox)
  854. {
  855.     //
  856.     // Do we have a selected item ???
  857.     //
  858.     if ( pVLBox->lSelItem != -1L )
  859.     {
  860.         long lSelected;
  861.         if ( (lSelected = SendMessage(pVLBox->hwndList, LB_GETCURSEL,
  862.              0, 0L)) == -1L ) {
  863.                //
  864.                // Current selction is visible....NOT
  865.                //
  866.                vlbRedrawOff(pVLBox);
  867.  
  868.                //
  869.                // Put selected item at top of LB
  870.                //
  871.                VLBFindPage(pVLBox, pVLBox->lSelItem, TRUE);
  872.  
  873.                //
  874.                // Scroll the LB down a line
  875.                //
  876.                VLBScrollDownLine(pVLBox);
  877.                SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  878.                SetFocus(pVLBox->hwndList);
  879.                SetSelectedItem(pVLBox);
  880.  
  881.                //
  882.                // Update the Screen
  883.                //
  884.                vlbRedrawOn(pVLBox);
  885.         }
  886.         else {
  887.                //
  888.                // Current selection is visible
  889.                //
  890.  
  891.                //
  892.                // Where is it ????
  893.                //
  894.                if ( (int)lSelected == (pVLBox->nLines-1) ) {
  895.                   //
  896.                   // At the Bottom... Scroll down 1 page less 1 line
  897.                   //                  Put selection at bottom
  898.                   //
  899.                   VLBScrollDownLine(pVLBox);
  900.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  901.                               pVLBox->nLines-1, 0L);
  902.                   SetFocus(pVLBox->hwndList);
  903.                   SetSelectedItem(pVLBox);
  904.                }
  905.                else {
  906.                    SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  907.                                (int)(lSelected)+1, 0L);
  908.                    SetFocus(pVLBox->hwndList);
  909.                    SetSelectedItem(pVLBox);
  910.                }
  911.         }
  912.     }
  913. }
  914.  
  915. void vlbLineUp(PVLBOX pVLBox)
  916. {
  917.     //
  918.     // Do we have a selected item ???
  919.     //
  920.     if ( pVLBox->lSelItem != -1L )
  921.     {
  922.         long lSelected;
  923.         if ( (lSelected = SendMessage(pVLBox->hwndList, LB_GETCURSEL,
  924.              0, 0L)) == -1L ) {
  925.                //
  926.                // Current selction is visible....NOT
  927.                //
  928.                vlbRedrawOff(pVLBox);
  929.  
  930.                //
  931.                // Put selected item at top of LB
  932.                //
  933.                VLBFindPage(pVLBox, pVLBox->lSelItem, TRUE);
  934.  
  935.                //
  936.                // Scroll the LB down a line
  937.                //
  938.                VLBScrollUpLine(pVLBox);
  939.                SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  940.                SetFocus(pVLBox->hwndList);
  941.                SetSelectedItem(pVLBox);
  942.  
  943.                //
  944.                // Update the Screen
  945.                //
  946.                vlbRedrawOn(pVLBox);
  947.         }
  948.         else {
  949.                //
  950.                // Current selection is visible
  951.                //
  952.  
  953.                //
  954.                // Where is it ????
  955.                //
  956.                if ( (int)lSelected == 0 ) {
  957.                   //
  958.                   // At the Bottom... Scroll up 1 page less 1 line
  959.                   //                  Put selection at bottom
  960.                   //
  961.                   VLBScrollUpLine(pVLBox);
  962.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  963.                   SetFocus(pVLBox->hwndList);
  964.                   SetSelectedItem(pVLBox);
  965.                }
  966.                else {
  967.                    SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  968.                                (int)(lSelected)-1, 0L);
  969.                    SetFocus(pVLBox->hwndList);
  970.                    SetSelectedItem(pVLBox);
  971.                }
  972.         }
  973.     }
  974. }
  975.  
  976.  
  977. void vlbPGDN(PVLBOX pVLBox)
  978. {
  979.     //
  980.     // Do we have a selected item ???
  981.     //
  982.     if ( pVLBox->lSelItem != -1L )
  983.     {
  984.         long lSelected;
  985.         if ( (lSelected = SendMessage(pVLBox->hwndList, LB_GETCURSEL,
  986.              0, 0L)) == -1L ) {
  987.                //
  988.                // Current selction is visible....NOT
  989.                //
  990.                vlbRedrawOff(pVLBox);
  991.  
  992.                //
  993.                // Put selected item at top of LB
  994.                //
  995.                VLBFindPage(pVLBox, pVLBox->lSelItem, TRUE);
  996.  
  997.                //
  998.                // Scroll the LB down a page
  999.                //
  1000.                VLBScrollDownPage(pVLBox, -1);
  1001.                SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  1002.                SetFocus(pVLBox->hwndList);
  1003.                SetSelectedItem(pVLBox);
  1004.  
  1005.                //
  1006.                // Update the Screen
  1007.                //
  1008.                vlbRedrawOn(pVLBox);
  1009.         }
  1010.         else {
  1011.                //
  1012.                // Current selection is visible
  1013.                //
  1014.  
  1015.                //
  1016.                // Where is it ????
  1017.                //
  1018.                if ( lSelected == 0L ) {
  1019.                   //
  1020.                   // At the top... put selection at bottom
  1021.                   //
  1022.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1023.                               pVLBox->nLines-1, 0L);
  1024.                   SetFocus(pVLBox->hwndList);
  1025.                   SetSelectedItem(pVLBox);
  1026.                }
  1027.                else if ( (int)lSelected == (pVLBox->nLines-1) ) {
  1028.                   //
  1029.                   // At the Bottom... Scroll down 1 page less 1 line
  1030.                   //                  Put selection at bottom
  1031.                   //
  1032.                   VLBScrollDownPage(pVLBox, -1);
  1033.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1034.                               pVLBox->nLines-1, 0L);
  1035.                   SetFocus(pVLBox->hwndList);
  1036.                   SetSelectedItem(pVLBox);
  1037.                }
  1038.                else {
  1039.                    //
  1040.                    // In the middle ... scroll down 1 page less
  1041.                    //                   the number of lines
  1042.                    //                   the selection is away
  1043.                    //                   from the bottom
  1044.                    //
  1045.                    //                   Put selection at bottom
  1046.                    //
  1047.                    int nAdjust;
  1048.                    nAdjust = -1 * (pVLBox->nLines-(int)lSelected);
  1049.                    VLBScrollDownPage(pVLBox, nAdjust);
  1050.                    SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1051.                                pVLBox->nLines-1, 0L);
  1052.                    SetFocus(pVLBox->hwndList);
  1053.                    SetSelectedItem(pVLBox);
  1054.                }
  1055.         }
  1056.     }
  1057. }
  1058.  
  1059.  
  1060. void vlbPGUP(PVLBOX pVLBox)
  1061. {
  1062.     //
  1063.     // Do we have a selected item ???
  1064.     //
  1065.     if ( pVLBox->lSelItem != -1L )
  1066.     {
  1067.         long lSelected;
  1068.         if ( (lSelected = SendMessage(pVLBox->hwndList, LB_GETCURSEL,
  1069.              0, 0L)) == -1L ) {
  1070.                //
  1071.                // Current selction is visible....NOT
  1072.                //
  1073.                vlbRedrawOff(pVLBox);
  1074.  
  1075.                //
  1076.                // Put selected item at top of LB
  1077.                //
  1078.                VLBFindPage(pVLBox, pVLBox->lSelItem, TRUE);
  1079.  
  1080.                //
  1081.                // Scroll the LB UP a page less 1 line
  1082.                //
  1083.                VLBScrollUpPage(pVLBox, -1);
  1084.                SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  1085.                SetFocus(pVLBox->hwndList);
  1086.                SetSelectedItem(pVLBox);
  1087.  
  1088.                //
  1089.                // Update the Screen
  1090.                //
  1091.                vlbRedrawOn(pVLBox);
  1092.         }
  1093.         else {
  1094.                //
  1095.                // Current selction is visible
  1096.                //
  1097.  
  1098.                //
  1099.                // Where is it ????
  1100.                //
  1101.                if ( lSelected == (pVLBox->nLines-1) ) {
  1102.                   //
  1103.                   // At the bottom... put selection at top
  1104.                   //
  1105.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1106.                               0, 0L);
  1107.                   SetFocus(pVLBox->hwndList);
  1108.                   SetSelectedItem(pVLBox);
  1109.                }
  1110.                else if ( (int)lSelected ==  0L) {
  1111.                   //
  1112.                   // At the TOP ... Scroll up 1 page less 1 line
  1113.                   //                  Put selection at top
  1114.                   //
  1115.                   VLBScrollUpPage(pVLBox, -1);
  1116.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1117.                               0, 0L);
  1118.                   SetFocus(pVLBox->hwndList);
  1119.                   SetSelectedItem(pVLBox);
  1120.                }
  1121.                else {
  1122.                    //
  1123.                    // In the middle ... scroll up 1 page less
  1124.                    //                   the number of lines
  1125.                    //                   the selection is away
  1126.                    //                   from the top
  1127.                    //
  1128.                    //                   Put selection at top
  1129.                    //
  1130.                    int nAdjust;
  1131.                    nAdjust = -1 * ((int)lSelected + 1 );
  1132.                    VLBScrollUpPage(pVLBox, nAdjust);
  1133.                    SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1134.                                0, 0L);
  1135.                    SetFocus(pVLBox->hwndList);
  1136.                    SetSelectedItem(pVLBox);
  1137.                }
  1138.         }
  1139.     }
  1140. }
  1141.